function MainAssistant(argFromPusher) {
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// declare global variables and define their defaults
this.needRefresh = false;
var gotGPSfix = false; 
var myPeriod = {value : "D"}; 
var myMinDate ={}; 
var interval; 
var myLastUpdated = new Date(); 
this.setMinDate('1w');

// open SQLite databses
var db = new Mojo.Depot({name:"dbLastData", version:1, replace:false},
			function(){ Mojo.Log.info("Open dbLastData OK");}, 
			function(err){ Mojo.Log.error("Open dbLastData NotOK", err.message);}
);

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MainAssistant.prototype = {
	
	setup: function() {
					myInfo("SETUP: Start function");
		this.currPrefs = { 
			lat: 0.0,
			lon: 0.0,
			mag: 0.1,
			dst: "K",
			maxDist: 20037.0,
			showInfo: true,
			period: "W",
			pageRefresh: 10,
			gotGPSfix: false,
			triedGPSalready: false
		};
		this.lstEQModel = {items: [{flynn_region: $L("Contacting web service...")}]};
		Ares.setupSceneAssistant(this);
					myInfo("SETUP: Ares.setupSceneAssistant(this) done");
		// define Application Menu ~~~~~~~~~~~~~~~~~~~~~~~~
		this.controller.setupWidget(Mojo.Menu.appMenu,
			this.attributes = {
				omitDefaultItems: true
			},
			this.model = {
				visible: true,
				items: [ 
					Mojo.Menu.editItem,
					{ label: $L("Preferences"), command: 'do-myPrefs' },
					// { label: $L("Help"), command: 'do-myHelp' },
					{ label: $L("About SeismiX"), command: 'do-myAbout'}
				]
			}
		);
		
		// define Command Menu ~~~~~~~~~~~~~~~~~~~~~~~~
		this.cmdMenuModel = {
			items: [ 
				{label: $L('Refresh'), icon: "sync", command: "do-Refresh"},
				{label: 'X', items : [
					{label: $L('Sort by'), submenu:'_sortMenu'},
					{label: $L('Period'), submenu:'_periodMenu'}
					]
				},
				{label: $L('Prefs'), iconPath: "images/gear32x32_1.png", command: "do-myPrefs"}
			]
		};
		this._sortMenuModel = {
			toggleCmd:'back',
			items: [
				{label: $L('Date/Time'), command:'do-sort-dat'}, 
				{label: $L('Distance'), command:'do-sort-dist'}, 
				{label: $L('Magnitude'), command:'do-sort-mag'}, 
				{label: $L('Region'), command:'do-sort-reg'}, 
				{label: $L('Depth'), command:'do-sort-dep'} 
			]
		};
		this._periodMenuModel = {
			items: [
				{label: $L('1 day'), command:'do-1d'},
				{label: $L('1 week'), command:'do-1w'}, 
				{label: $L('1 month'), command:'do-1m'}
			]
		};
		this.controller.setupWidget(Mojo.Menu.commandMenu, undefined, this.cmdMenuModel);
		this.controller.setupWidget('_sortMenu', undefined, this._sortMenuModel);
		this.controller.setupWidget('_periodMenu', undefined, this._periodMenuModel);
		
		// define and display scrim and spinner ~~~~~~~~~~~~~~~~~~~~~~~~
		this.scrim = Mojo.View.createScrim(this.controller.document, {scrimClass:'palm-scrim'});
		this.controller.setupWidget("mySpinner",
			this.attributes = {
				spinnerSize: "large"
			},
			this.model = {
				spinning: true 
			}
		); 
		this.controller.get("myScrim").appendChild(this.scrim).appendChild($(mySpinner));
		this.needRefresh = true;
					myInfo("SETUP: End function");
	}, //end setup: function
	
	activate: function(args){
					myInfo("ACTIVATE: Start function");
					myInfo("ACTIVATE:Before start getCurrentPosition()");
					// try to get a quick location fix or get the position from myLocation-settings
		this.$.gps.getCurrentPosition();
					myInfo("ACTIVATE:After start getCurrentPosition()");
		if (this.needRefresh === true) {
					myInfo("ACTIVATE: needRefresh = true");
					myInfo("SETUP:Before start getPreferences()");
			this.getPrefs();
					myInfo("SETUP:After start getPreferences()");
			window.clearInterval(interval);
			interval = window.setInterval(this.getEQdata.bind(this), (this.currPrefs.pageRefresh * 60 * 1000));
			this.lstEQModel = {items: [{flynn_region: $L("Contacting web service...")}]};
			this.controller.modelChanged(this.lstEQModel);
			this.getEQdata();
			this.needRefresh = false;
		}
					myInfo("ACTIVATE: End function");
	},
	
	cleanup: function() {
		Ares.cleanupSceneAssistant(this);
	},
	
	handleCommand: function(event) {
		if (event.type === Mojo.Event.command) {
			if (event.command == 'do-Refresh') { 
					this.getEQdata();
			}
			if (event.command == "do-myPrefs") {
				this.controller.stageController.pushScene("scnPrefs");
			}
			if (event.command == "do-myAbout") {
				this.controller.stageController.pushScene("scnAbout");
			}
			if (event.command == 'do-KillCookie') { 
				try {
					var PrefsCookie = new Mojo.Model.Cookie('PrefsCookie');
					PrefsCookie.remove();
					Mojo.Controller.getAppController().showBanner({messageText: $L("Cookie deleted."), icon: "images/day-event-info-press.png"},{source: 'notification'}, "SeismiX");
				}
				catch(err) {
					Mojo.Controller.errorDialog("Could not delete cookie.");
				}
			}
			if (event.command == "do-myHelp") {
			}
			if (event.command == 'do-1d') {
				setMinDate("1d");
				this.getEQdata();
			}
			if (event.command == 'do-1w') {
				setMinDate("1w");
				this.getEQdata();
			}
			if (event.command == 'do-1m') {
				setMinDate("1m");
				this.getEQdata();
			}
			if (event.command == 'do-sort-dat') {
				this.lstEQModel.items.sort(sort_by("datetime", true));
				this.controller.modelChanged(this.lstEQModel);
			}
			if (event.command == 'do-sort-dist') {
				this.lstEQModel.items.sort(sort_by("dist", false, parseInt));
				this.controller.modelChanged(this.lstEQModel);
			}
			if (event.command == 'do-sort-mag') {
				this.lstEQModel.items.sort(sort_by("mag", true, parseFloat));
				this.controller.modelChanged(this.lstEQModel);
			}
			if (event.command == 'do-sort-reg') {
				this.lstEQModel.items.sort(sort_by("flynn_region", false));
				this.controller.modelChanged(this.lstEQModel);
			}
			if (event.command == 'do-sort-dep') {
				this.lstEQModel.items.sort(sort_by("depth", false, parseFloat));
				this.controller.modelChanged(this.lstEQModel);
			}
		}
	},
	
	getPrefs: function() {
					myInfo("GETPREFS: Start function");
		var prefsCookie = new Mojo.Model.Cookie('PrefsCookie');
		var prefsData;
		try {
			prefsData = prefsCookie.get();
		}
		catch(err) {
			Mojo.Controller.errorDialog($L("Could not read the cookie storing the preferences."));
		}
		if (prefsData !== undefined) { 
			// if no GPS fix available, take the coordinates from preferences, otherwise don't touch them, as set by the GPS fix
			if (this.currPrefs.gotGPSfix == false) {;
				this.currPrefs.lat = prefsData.myLat;
				this.currPrefs.lon = prefsData.myLon;
			}
			this.currPrefs.mag = prefsData.myMag;
			this.currPrefs.dst = prefsData.myDist;
			this.currPrefs.maxDist = prefsData.myMaxDist;
			this.currPrefs.showInfo = prefsData.myShowInfo;
			this.currPrefs.pageRefresh = prefsData.myPageRefresh;
			this.currPrefs.override = prefsData.myOverride;
		}
					myInfo("GETPREFS: End function");
	},
	
	getWSdata: function(){
						myInfo("GETWSDATA: Start function");
		if (this.$.ws1.isReady()){
						myInfo("GETWSDATA: isReady = true");
			$("myScrim").show();
			this.getPrefs();
			var params = {};
			params.limit="1000";
			params.format="json";
			params.sort="datetime";
			params.dir="DESC";
			params.magMin = this.currPrefs.mag;
			if (myMinDate.value) {params.dateMin=myMinDate.value;}
			this.$.ws1.setParameters(params);
			this.$.ws1.execute();
		}
		else {
					myInfo("GETWSDATA: isReady = false");
			this.ws1Cancel();
		}
					myInfo("GETWSDATA: End function");
	},

	getEQdata: function() {
		this.getWSdata();
	},
	
	ws1Success: function(inSender, inResponse, inRequest) {
					myInfo("WS1SUCCESS: Start function");
		$("myScrim").hide();
		if (inResponse !== undefined) {
			try{
				// filter earthquakes based on myMaxDist parameter and assign the resulting array to the lstEQModel
				var myNewItems = [];
				var myItems = inResponse.unids;
				var lati = this.currPrefs.lat;
				var loni = this.currPrefs.lon;
				var dsti = this.currPrefs.dst;
				var maxDisti = this.currPrefs.maxDist;
				myItems.each(
					function(name, index){
						if (parseFloat(lati) != 0 && parseFloat(loni) != 0) {
							name.dist = calcDist(parseFloat(name.lat), parseFloat(name.lon), parseFloat(lati), parseFloat(loni), dsti).toFixed();
							if (!isNaN(name.dist)){
								switch(dsti) {
									case "M":
										name.distString = addCommas(name.dist) + " mi";
									break;
									case "N":
										name.distString = addCommas(name.dist) + " NM";
									break;
									default:
										name.distString = addCommas(name.dist) + " km";
								}
							}
							else {
								name.distString = inModel.dist;
							}
							if (parseInt(name.dist, 10) <= parseInt(maxDisti, 10)) {
								myNewItems.push(name);
							}
						}
						else {
							name.dist = $L("NO DIST.");
							myNewItems.push(name);
						}
				}, myItems);
				this.lstEQModel = {
					items : myNewItems
				};
				this.controller.setWidgetModel('lstEQ', this.lstEQModel);
				this.controller.modelChanged(this.lstEQModel);
				Mojo.Log.info("+++++Retrieved ", myItems.length, "/", myNewItems.length, " records");
			}
			catch(err){
				Mojo.Controller.getAppController().showBanner({messageText: $L("Data refresh failed!"), icon: "images/small-error-icon.png"},{source: 'notification'}, "SeismiX");
				return;
			}
			// save latest displayed data from lstEQModel to a database
			if (this.lstEQModel){
				db.add("lastData", JSON.stringify(this.lstEQModel),
					function(){
						Mojo.Log.info("Saving LastData to dbLastData OK");
						Mojo.Controller.getAppController().showBanner({messageText: $L("Data refresh completed") + ". (" + myNewItems.length + " " + $L("items") + ")", icon: "images/day-event-info-press.png"},{source: 'notification'}, "SeismiX");
					}, 
					function(trans, result){
						Mojo.Log.error("Saving LastData to dbLastData NotOK", result.message);
					}
				);
				var lastUpd = myLastUpdated.toLocaleDateString() + " " + myLastUpdated.toLocaleTimeString();
				db.add("lastUpdated", lastUpd);
			}
		}
		myInfo("WS1SUCCESS: End function");
	},
	
	getLastDataOK: function(d){
		if (d !== null && d !== undefined) {
			Mojo.Log.info("Get LastData from dbLastData OK");
			this.lstEQModel = JSON.parse(d);
			this.controller.setWidgetModel('lstEQ', this.lstEQModel);
			this.controller.modelChanged(this.lstEQModel);
			Mojo.Controller.getAppController().showBanner({messageText: $L("Displaying data from last refresh."), icon: "images/day-event-info-press.png"},{source: 'notification'}, "SeismiX");
		}
	}, 
	
	getLastDataFailed: function(err) {
		Mojo.Log.error("Get LastData from dbLastData NotOK", err);
	},

	getLatestData: function() {
		this.lstEQModel = {items: [{flynn_region: $L("No data to display")}]};
		this.controller.setWidgetModel('lstEQ', this.lstEQModel);
		this.controller.modelChanged(this.lstEQModel);
		myInfo("GETLATESTDATA: Start function");
		try {
			myInfo("GETLATESTDATA: Try to get latest data from DB");
			db.get("lastData", this.getLastDataOK.bind(this), this.getLastDataFailed.bind(this));
		}
		catch(err) {
			myInfo("GETLATESTDATA: Failed!");
			getLastDataFailed(err);
		}
		myInfo("GETLATESTDATA: End function");
	},
	
	ws1Cancel: function () {
					myInfo("WS1CANCEL: Start function");
		$("myScrim").hide();
		this.$.ws1.cancel();
					myInfo("WS1CANCEL: End function");
	},

	ws1Failure: function(inSender, inError) {
					myInfo("WS1FAILURE: Start function", inError.status, inError.statusText );
		$("myScrim").hide();
		var str = $L("Request to web service failed.");
		if (inError.status !== null) {
			str = str + " Status: " + inError.status;
		}
		Mojo.Controller.errorDialog(str);
		this.getLatestData();
					myInfo("WS1FAILURE: End function");
	},
	
	lstEQListtap: function(inSender, event) {
		var _dist = "";
		switch(this.currPrefs.dst) {
			case "M":
				 _dist = " mi";
			break;
			case "N":
				_dist = " NM";
			break;
			default:
				_dist = " km";
		}
		var argForPushing = {
			lon : event.item.lon,
			lat : event.item.lat,
			mag : event.item.mag,
			dep : event.item.depth + " km",
			reg : event.item.flynn_region,
			dat : event.item.datetime,
			dist : event.item.dist + _dist,
			showInfo : this.currPrefs.showInfo
			};
		this.controller.stageController.pushScene("scnMapping", argForPushing);
	},
	
	lstEQFormat: function(inSender) {
		return {
			propertyName: function(inValue, inModel) {
				if ((inModel.lat) && (inModel.lon)) {
					inModel.depthString = inModel.depth.replace("km","") + " km";
					inModel.magtype = inModel.magtype.capitalize();
					inModel.flynn_region = inModel.flynn_region.capitalize();
					inModel.dist = inModel.dist.replace(" km","");
					inModel.dist = inModel.dist.replace(",","");
				}
				return inValue;
			}
		};
	},
	
	gpsSuccess: function(inSender, inResponse, inRequest) {
					myInfo("GPSSUCCESS: Start function", JSON.stringify(inResponse));
		if (inResponse !== 'undefined') {
			this.currPrefs.gotGPSfix = true;
			this.currPrefs.lat = inResponse.latitude;
			this.currPrefs.lon = inResponse.longitude;
			if (this.currPrefs.override == 1) {
				var PrefsCookie = new Mojo.Model.Cookie('PrefsCookie');
				try {
					var PrefsData = PrefsCookie.get();
					PrefsData.myLat = inResponse.latitude;
					PrefsData.myLon = inResponse.longitude;
					PrefsCookie.put(PrefsData);
				}
				catch (err) {
					Mojo.Log.error(" ### Could not write preferences cookie with lat/lon of last fix.");
				}
			}
		}
					myInfo("GPSSUCCESS: End function");
	},
	
	gpsFailure: function(inSender, inError) {
					myInfo("GPSFAILURE: Start function", JSON.stringify(inError));
		this.currPrefs.gotGPSfix = false;
						// Mojo.Log.info("GPS-Failure. ErrorCode: ", inError.errorCode);
		if (this.currPrefs.lat == 0 && this.currPrefs.lon == 0) {
						// Show alert dialog allowing user to either enter his location in the Prefs or open Location Svc. to switch GPS on.
						myInfo("GPSFAILURE: lat and lon = 0, no GPS fix, showing alert");
		var myChoices = [];
		if (this.currPrefs.triedGPSalready == false ) {
			myChoices.push({label:$L('Retry to get a fix'), value:'Retry', type:'affirmative'});
						myInfo("GPSFAILURE: showing alert the first time");
		}
		else {
			myChoices.push({label:$L('Retry to get a fix'), value:'Retry', type:'secondary'});
						myInfo("GPSFAILURE: showing alert the second+ time");
		}
		myChoices.push({label:$L('Open Location Services'), value:'LocSvc', type:'affirmative'});
		myChoices.push({label:$L('Open preferences'), value:'Prefs', type:'affirmative'});

			this.controller.showAlertDialog({
				preventCancel: false,
				onChoose: function(value) {
					if (value == 'Prefs') {
						this.controller.stageController.pushScene("scnPrefs");
					}
					if (value == 'LocSvc') {
						this.controller.serviceRequest('palm://com.palm.applicationManager', {
							method: 'launch',
							parameters:  {
								id: 'com.palm.app.location',
								params: {}
							}
						});
					}
					if (value == 'Retry') {
						this.currPrefs.triedGPSalready = true;
						this.$.gps.getCurrentPosition();
					}
					if (value == 'undefined') {
					}
				},
				title: $L("Your location is unknown!"),
				message: $L({value: "Cannot calculate distance without knowing your current location. Either switch on GPS/Location Services or enter your coordinates in the preferences screen. Note: After switching GPS on it may take several minutes until your location can be fixed.", key: "noMyLoc"}),
				choices: myChoices
			});
		}
		myInfo("GPSFAILURE: End function");
	}
};
